package business.knBase;

import java.util.HashMap;

import groovy.sql.Sql;
import org.apache.log4j.Logger;

import business.threads.Monitor;


/**
 * Factoria abstracta para los DAO de knbase
 * @author Administrador
 *
 */
public class AbsKnBaseDAOFactory {

	private static AbsKnBaseDAOFactory _instance;
	/**
	 * Objeto para bloquear y permitir un singleton threadsafe
	 */
	private static Object syncObject_ = new Object();
	private Logger _log;
	/**
	 * Este es el objeto que se encarga de acceder a la base de datos SQLite
	 */
	private HashMap<Integer,Sql> sqlitePool;

	
	/**
	 * TODO: hacer thread safe
	 * @return instancia unica
	 */
	public static AbsKnBaseDAOFactory getInstance() {

		if (_instance == null) {
			
						  synchronized(syncObject_) {
			
							if (_instance == null) {
							   _instance = new AbsKnBaseDAOFactory();
							}
			
						  }
			
						}
		return _instance;
	}
	
	private AbsKnBaseDAOFactory() {
		_log = Logger.getLogger("AbsSqliteDAOFactory");
		sqlitePool = new HashMap<Integer,Sql>();
		
	}
	
	/**
	 * Crea una nueva conexion para el modelo a la base knbase.db

	 */
	public void startConnection(Integer modelId) {
		
		_log.info "Configurando el acceso a knbase"
		boolean ok = false
		close(modelId);
		_log.info "Creando una nueva instancia sqlite para knBase"
			
		if (!sqlitePool.containsKey(modelId)) {
				Sql sqlite1 = groovy.sql.Sql.newInstance("jdbc:sqlite:knBase.db","org.sqlite.JDBC")
				sqlitePool.put(modelId,sqlite1);
			}

	}
	
	/**
	* Cierra sqlite
	*/
	public boolean close(Integer id) {
		boolean ok = false;
	   try {
		   
		   if (sqlitePool.containsKey(id)) {
			   sqlitePool.get(id).close();
			   sqlitePool.remove(id);
		   }
			ok = true;
	   } catch (Exception e) {
	   	_log.error "Error cerrando sqlite. ${e.getMessage()}"
	   }
	   return ok;
	}
	
	/**
	 * Cierra todas las conexiones que hayan podido quedar
	 */
	public void closeAll() {
		sqlitePool.keySet().each { id ->
			try {
				 sqlitePool.get(id).close();
				
			} catch (Exception e) {
				
			}
		}
		_instance = null;
	}
	
	/**
	* Inicia transaccion en sqlite
	*/
	 public void startTransaction(Integer modelId) { sqlitePool.get(modelId).execute("BEGIN TRANSACTION");}
	 
	 
	 
	
	 /**
	  * finaliza transaccion en sqlite. Equivalente a hacer un COMMIT
	  */
	 public void endTransaction(Integer id) {
		  
			sqlitePool.get(id).execute("END TRANSACTION");}
	 /**
	  * Hace un rollback sobre la transaccion abierta
	  */
	 public void rollback(Integer id) {  
			sqlitePool.get(id).execute("ROLLBACK TRANSACTION");}
	 
	 /**
	  * Compacta la base de datos
	  */
	 public void vacuum(Integer id) {
		  
			sqlitePool.get(id).execute "VACUUM"
	 }
	
	public KnBaseGenericDAO getSpainWordDAO(Integer id) {
		return new KnBaseGenericDAO(sqlitePool.get(id),"countryword");
	}
	
	public KnBaseGenericDAO getExcludesDAO(Integer id) {
		
		return new KnBaseGenericDAO(sqlitePool.get(id),"Excludes");
	}
	
	public KnBaseGenericDAO getForeignWithSpainDAO(Integer id) {
		
		return new KnBaseGenericDAO(sqlitePool.get(id),"ForeignWithSpain");
	}
	
	public KnBaseGenericDAO getForeignWordDAO(Integer id) {
		
		return new KnBaseGenericDAO(sqlitePool.get(id),"ForeignWord");
	}
	
	public KnBaseGenericDAO getProvinciasDAO(Integer id) {
		
		return new KnBaseGenericDAO(sqlitePool.get(id),"Provincias");
	}
	
	public KnBaseGenericDAO getRegionsDAO(Integer id) {
		
		return new KnBaseGenericDAO(sqlitePool.get(id),"Regions");
	}
	
	public KnBaseGenericDAO getSectorDAO(Integer id) {
		
		return new KnBaseGenericDAO(sqlitePool.get(id),"Sector");
	}
	
	public KnBaseGenericDAO getSpanishForeignDAO(Integer id) {
		
		return new KnBaseGenericDAO(sqlitePool.get(id),"SpanishForeign");
	}
	
	static main (args) {
		AbsKnBaseDAOFactory.getInstance().startConnection(3);
		AbsKnBaseDAOFactory.getInstance().getRegionsDAO(3).selectAll().each { knbase ->
			println knbase
			
		}
		AbsKnBaseDAOFactory.getInstance().getProvinciasDAO(3).selectAll().each { knbase ->
			println knbase
			
		}
	}
	
}
